/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package montecarlo;

import static java.lang.Math.exp;
import static java.lang.Math.max;
import static java.lang.Math.sqrt;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;


/**
 *
 * @author Valentin
 */
public class MonteCarlo {

    /**
     * @param args the command line arguments
     */

    
    public static void main(String[] args) throws InterruptedException, ExecutionException
    {
    int nSimulations=100000;
    Long t0, t1;
    final MonteCarloFonctions mc = new MonteCarloFonctions();
    
    /*
    //Calcul en monothread
    t0=System.currentTimeMillis();
    mc.MonteCarloStandardOption();
    t1=System.currentTimeMillis();
    System.out.println("résultat calculé en "+(t1-t0)+" mS"); */


    
    
    
    //Calcul en multithread
    final int numberOfCores = Runtime.getRuntime().availableProcessors();
    final double blockingCoefficient = 0.9;
    final int poolSize = (int)(numberOfCores / (1 - blockingCoefficient));

    final List<Callable<Double>> partitions = new ArrayList<Callable<Double>>();//crée la liste des taches à exécuter
    
    
    for(int i=0; i<nSimulations; i++)//ajouter les taches dans la liste
	{
      partitions.add(new Callable<Double>()
	  {
        public Double call() throws Exception
		{
          return mc.MonteCarloUneSimulation();//tache à exécuter
        }        
      });
    }
    
    ExecutorService pool = Executors.newFixedThreadPool(poolSize);//créer la pool de thread
    final List<Future<Double>> valueOfStocks = pool.invokeAll(partitions, 10000, TimeUnit.SECONDS);//créer la liste des résultats des taches
    
    
    t0=System.currentTimeMillis();//temps de début
    pool.invokeAll(partitions, 10000, TimeUnit.SECONDS);//exécute la pool de thread
    
    
    double Total = 0.0; 
    for(final Future<Double> valueOfAStock : valueOfStocks)
    {
      Total += valueOfAStock.get();//sommer tous les résultats
    }
    
    pool.shutdown();//quitter la pool
    
    
   Total=Total/nSimulations;//moyenne des résultats
   
   t1=System.currentTimeMillis();//temps de fin
   
        System.out.println(Total);
        System.out.println("Calculé en "+(t1-t0)+" mS");
 
    }
}
